package icu.zhhll.util.io;

import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

/**
 * gzip压缩
 *
 * @author zh
 * @date 2023/8/10 16:16
 */
public class GzipUtils {

    /**
     * 压缩字符串
     *
     * @param str
     * @return
     */
    public static byte[] compress(String str) throws IOException {
        if (StringUtils.isBlank(str)) {
            return null;
        }

        return compress(str.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 压缩文件内容
     *
     * @param file
     * @return
     */
    public static byte[] compressFileContent(File file) {
        if (file == null) {
            throw new RuntimeException("文件不能为空");
        }
        try {
            return compress(Files.readAllBytes(Paths.get(file.getPath())));
        } catch (IOException e) {
            throw new RuntimeException("读取文件失败");
        }
    }

    /**
     * 压缩文件
     *
     * @param source
     * @param target
     */
    public static void compressFile(File source, String target) throws IOException {

        try (FileInputStream fin = new FileInputStream(source);
             FileOutputStream fout = new FileOutputStream(target);
             GZIPOutputStream gzout = new GZIPOutputStream(fout)) {

            byte[] buf = new byte[1024];
            int num;
            while ((num = fin.read(buf)) != -1) {
                gzout.write(buf, 0, num);
            }
        }
    }

    /**
     * 压缩文件
     *
     * @param source
     * @param target
     */
    public static void compressFile(String source, String target) throws IOException {

        try (FileInputStream fin = new FileInputStream(source);
             FileOutputStream fout = new FileOutputStream(target);
             GZIPOutputStream gzout = new GZIPOutputStream(fout)) {

            byte[] buf = new byte[1024];
            int num;
            while ((num = fin.read(buf)) != -1) {
                gzout.write(buf, 0, num);
            }
        }
    }

    /**
     * 压缩
     *
     * @param val
     * @return
     */
    public static byte[] compress(byte[] val) throws IOException {
        try (ByteArrayOutputStream bos = new ByteArrayOutputStream(val.length); GZIPOutputStream gos =
                new GZIPOutputStream(bos)) {
            gos.write(val, 0, val.length);
            gos.finish();
            gos.flush();
            bos.flush();
            val = bos.toByteArray();
        }
        return val;
    }

    /**
     * 解压缩
     *
     * @param buf
     * @return
     * @throws IOException
     */
    public static byte[] decompress(byte[] buf) throws IOException {
        ByteArrayOutputStream bos;
        try (GZIPInputStream gzi = new GZIPInputStream(new ByteArrayInputStream(buf))) {
            bos = new ByteArrayOutputStream(buf.length);
            int count;
            byte[] tmp = new byte[2048];
            while ((count = gzi.read(tmp)) != -1) {
                bos.write(tmp, 0, count);
            }
            buf = bos.toByteArray();
        }
        return buf;
    }

    /**
     * 解压文件
     *
     * @param source
     * @param target
     * @throws IOException
     */
    public static void decompressFile(String source, String target)
            throws IOException {

        try (FileInputStream fin = new FileInputStream(source);
             GZIPInputStream gzin = new GZIPInputStream(fin);
             FileOutputStream fout = new FileOutputStream(target)) {

            byte[] buf = new byte[1024];
            int num;
            while ((num = gzin.read(buf, 0, buf.length)) != -1) {
                fout.write(buf, 0, num);
            }
        }

    }

    /**
     * 解压文件
     *
     * @param source
     * @param target
     * @throws IOException
     */
    public static void decompressFile(File source, String target)
            throws IOException {

        try (FileInputStream fin = new FileInputStream(source);
             GZIPInputStream gzin = new GZIPInputStream(fin);
             FileOutputStream fout = new FileOutputStream(target)) {

            byte[] buf = new byte[1024];
            int num;
            while ((num = gzin.read(buf, 0, buf.length)) != -1) {
                fout.write(buf, 0, num);
            }
        }

    }

}
